// QtMyBatisPlus.cpp
#include <QString>
#include "qtmybatisplus.h"
#include "transaction.h"
namespace QtMyBatisPlus {



/********************* QueryWrapper 实现 *********************/
QueryWrapper::QueryWrapper()
    : m_offset(0), m_limit(0) {}

QueryWrapper& QueryWrapper::eq(const QString& column, const QVariant& value) {
    if (value.isValid()) {
        addCondition(column, "=", value);
    }
    return *this;
}

QueryWrapper& QueryWrapper::ne(const QString& column, const QVariant& value) {
    if (value.isValid()) {
        addCondition(column, "<>", value);
    }
    return *this;
}

QueryWrapper& QueryWrapper::gt(const QString& column, const QVariant& value) {
    if (value.isValid()) {
        addCondition(column, ">", value);
    }
    return *this;
}

QueryWrapper& QueryWrapper::ge(const QString& column, const QVariant& value) {
    if (value.isValid()) {
        addCondition(column, ">=", value);
    }
    return *this;
}

QueryWrapper& QueryWrapper::lt(const QString& column, const QVariant& value) {
    if (value.isValid()) {
        addCondition(column, "<", value);
    }
    return *this;
}

QueryWrapper& QueryWrapper::le(const QString& column, const QVariant& value) {
    if (value.isValid()) {
        addCondition(column, "<=", value);
    }
    return *this;
}

QueryWrapper& QueryWrapper::between(const QString& column, const QVariant& low, const QVariant& high) {
    if (low.isValid() && high.isValid()) {
        QString param = sanitizeKey(column);
        m_conditions.append(QString("%1 BETWEEN :%2_low AND :%2_high").arg(column).arg(param));
        m_params.insert(param + "_low", low);
        m_params.insert(param + "_high", high);
    }
    return *this;
}

QueryWrapper& QueryWrapper::notBetween(const QString& column, const QVariant& low, const QVariant& high) {
    if (low.isValid() && high.isValid()) {
        QString param = sanitizeKey(column);
        m_conditions.append(QString("%1 NOT BETWEEN :%2_low AND :%2_high").arg(column).arg(param));
        m_params.insert(param + "_low", low);
        m_params.insert(param + "_high", high);
    }
    return *this;
}

QueryWrapper& QueryWrapper::in(const QString& column, const QVariantList& values) {
    if (!values.isEmpty()) {
        QStringList placeholders;
        QString paramBase = sanitizeKey(column);
        for (int i = 0; i < values.size(); ++i) {
            QString param = paramBase + "_in_" + QString::number(i);
            placeholders.append(":" + param);
            m_params.insert(param, values[i]);
        }
        m_conditions.append(QString("%1 IN (%2)").arg(column).arg(placeholders.join(", ")));
    }
    return *this;
}

QueryWrapper& QueryWrapper::notIn(const QString& column, const QVariantList& values) {
    if (!values.isEmpty()) {
        QStringList placeholders;
        QString paramBase = sanitizeKey(column);
        for (int i = 0; i < values.size(); ++i) {
            QString param = paramBase + "_in_" + QString::number(i);
            placeholders.append(":" + param);
            m_params.insert(param, values[i]);
        }
        m_conditions.append(QString("%1 NOT IN (%2)").arg(column).arg(placeholders.join(", ")));
    }
    return *this;
}

QueryWrapper& QueryWrapper::like(const QString& column, const QString& value) {
    if (!value.isEmpty()) {
        addCondition(column, "LIKE", QVariant("%" + value + "%"));
    }
    return *this;
}

QueryWrapper& QueryWrapper::notLike(const QString& column, const QString& value) {
    if (!value.isEmpty()) {
        addCondition(column, "NOT LIKE", QVariant("%" + value + "%"));
    }
    return *this;
}

QueryWrapper& QueryWrapper::startsWith(const QString& column, const QString& value) {
    if (!value.isEmpty()) {
        addCondition(column, "LIKE", QVariant(value + "%"));
    }
    return *this;
}

QueryWrapper& QueryWrapper::endsWith(const QString& column, const QString& value) {
    if (!value.isEmpty()) {
        addCondition(column, "LIKE", QVariant("%" + value));
    }
    return *this;
}

QueryWrapper& QueryWrapper::isNull(const QString& column) {
    m_conditions.append(QString("%1 IS NULL").arg(column));
    return *this;
}

QueryWrapper& QueryWrapper::isNotNull(const QString& column) {
    m_conditions.append(QString("%1 IS NOT NULL").arg(column));
    return *this;
}

QueryWrapper& QueryWrapper::orCondition(const QueryWrapper& other) {
    if (!other.m_conditions.isEmpty()) {
        m_orConditions.append(other);
    }
    return *this;
}

QueryWrapper& QueryWrapper::orNew(const QueryWrapper& other) {
    return orCondition(other);
}

QueryWrapper& QueryWrapper::notCondition(const QueryWrapper& other) {
    if (!other.m_conditions.isEmpty()) {
        QString whereClause = other.buildWhereClause();
        if (whereClause.startsWith("WHERE ")) {
            whereClause = whereClause.mid(6);
        }
        m_conditions.append("NOT (" + whereClause + ")");

        // 合并参数
        QVariantMap otherParams = other.allParams();
        for (auto it = otherParams.constBegin(); it != otherParams.constEnd(); ++it) {
            m_params.insert(it.key(), it.value());
        }
    }
    return *this;
}

QueryWrapper& QueryWrapper::orderByAsc(const QString& column) {
    m_orderBy = QString("ORDER BY %1 ASC").arg(column);
    return *this;
}

QueryWrapper& QueryWrapper::orderByDesc(const QString& column) {
    m_orderBy = QString("ORDER BY %1 DESC").arg(column);
    return *this;
}

QueryWrapper& QueryWrapper::groupBy(const QString& column) {
    m_groupBy = QString("GROUP BY %1").arg(column);
    return *this;
}

QueryWrapper& QueryWrapper::page(int pageNum, int pageSize) {
    m_offset = (pageNum - 1) * pageSize;
    m_limit = pageSize;
    return *this;
}

QString QueryWrapper::buildWhereClause() const {
    QStringList allConditions = m_conditions;

    for (const auto& orWrapper : m_orConditions) {
        QString orClause = orWrapper.buildWhereClause();
        if (!orClause.isEmpty()) {
            if (orClause.startsWith("WHERE ")) {
                orClause = orClause.mid(6);
            }
            allConditions.append("(" + orClause + ")");
        }
    }

    if (allConditions.isEmpty()) return "";
    return "WHERE " + allConditions.join(" AND ");
}

QString QueryWrapper::buildSqlClause() const {
    QString sql;

    QString whereClause = buildWhereClause();
    if (!whereClause.isEmpty()) {
        sql += " " + whereClause;
    }

    if (!m_groupBy.isEmpty()) {
        sql += " " + m_groupBy;
    }

    if (!m_orderBy.isEmpty()) {
        sql += " " + m_orderBy;
    }

    if (m_limit > 0) {
        sql += QString(" OFFSET %1 ROWS FETCH NEXT %2 ROWS ONLY").arg(m_offset).arg(m_limit);
    }

    return sql;
}

QVariantMap QueryWrapper::allParams() const {
    QList<QVariantMap> allParamMaps;
    allParamMaps.append(m_params);

    for (const auto& orWrapper : m_orConditions) {
        allParamMaps.append(orWrapper.allParams());
    }

    return QVariantUtils::safeMerge(allParamMaps);
}

void QueryWrapper::addExtraParam(const QString& key, const QVariant& value) {
    m_extraParams.insert(key, value);
}

QVariantMap QueryWrapper::allParamsWithExtra() const {
    QVariantMap params = allParams();
    for (auto it = m_extraParams.constBegin(); it != m_extraParams.constEnd(); ++it) {
        params.insert(it.key(), it.value());
    }
    return params;
}

void QueryWrapper::addCondition(const QString& column, const QString& op, const QVariant& value) {
    QString param = sanitizeKey(column);
    m_conditions.append(QString("%1 %2 :%3").arg(column).arg(op).arg(param));
    m_params.insert(param, value);
}

QString QueryWrapper::sanitizeKey(const QString& key) const {
    QString keyTmp = key ;
    keyTmp.replace('.', '_').replace(' ', '_').replace('(', '_').replace(')', '_');

    return keyTmp ;
}


} // namespace QtMyBatisPlus
